﻿using System;
using System.Threading;

namespace GojiSoft.EventSequenceUnitTesting.ExampleSupport {
    public static class Synchronization {
        #region Private Methods

        private static void BlockWithTimeout(int timeoutMS, string timeoutMessage, Func<int, bool> blockingFunction) {
            bool timedOut = !blockingFunction(timeoutMS);

            if(timedOut) {
                string message = "Operation timed out after waiting for " + timeoutMS + "ms.";

                message = (timeoutMessage != null) ? (message + " " + timeoutMessage) : message;

                throw new TimeoutException(message);
            }
        }

        #endregion

        #region Public Methods

        public static bool Wait(WaitHandle @event, int timeoutMS) {
            if(@event == null)
                throw new ArgumentNullException("event");

            return @event.WaitOne(timeoutMS, true);
        }

        public static void WaitWithTimeout(WaitHandle @event, int timeoutMS, string timeoutMessage) {
            if(@event == null)
                throw new ArgumentNullException("event");

            BlockWithTimeout(timeoutMS, timeoutMessage, @event.WaitOne);
        }

        public static bool Join(Thread thread, int timeoutMS) {
            if(thread == null)
                throw new ArgumentNullException("thread");

            return thread.Join(timeoutMS);
        }

        public static void JoinWithTimeout(Thread thread, int timeoutMS, string timeoutMessage) {
            if(thread == null)
                throw new ArgumentNullException("thread");

            BlockWithTimeout(timeoutMS, timeoutMessage, thread.Join);
        }

        #endregion
    }
}
